"""
Personality templates for the emobot project.
"""

import json
from typing import Dict, List, Tuple, Optional
from datetime import datetime


class PersonalityRecognitionTemplates:
    """Templates for personality recognition and analysis."""

    # 性格识别所需的最小对话轮数（设为1，每次对话都分析）
    MIN_CONVERSATION_ROUNDS = 1

    @staticmethod
    def analyze_conversation_only(
        conversation: str, user_id: str, existing_personality_data: dict = None
    ) -> dict:
        """基于多轮对话进行性格分析，每次对话结束调用LLM进行分析"""
        # 分析对话轮数
        conversation_lines = conversation.strip().split("\n")

        # 计算对话轮数
        user_messages = []
        for line in conversation_lines:
            line = line.strip()
            # 标准格式检测
            if (
                line.startswith("用户:")
                or line.startswith("User:")
                or line.startswith("用户：")
                or line.startswith("User：")
                or line.startswith("用户")
                or line.startswith("User")
            ):
                user_messages.append(line)

        # 如果没有找到标准格式，使用备用检测
        if not user_messages:
            assistant_prefixes = ["助手", "Bot", "Assistant", "AI", "机器人", "系统"]
            user_messages = [
                line.strip()
                for line in conversation_lines
                if line.strip()
                and not any(
                    line.strip().startswith(prefix) for prefix in assistant_prefixes
                )
            ]

        conversation_rounds = len(user_messages)

        # 构建LLM分析提示词
        prompt = PersonalityRecognitionTemplates.build_llm_personality_prompt(
            conversation, user_id
        )

        # 添加分析时间戳
        analysis_timestamp = datetime.now().isoformat()

        return {
            "user_id": user_id,
            "personality": "llm_analyzed",
            "conversation_rounds": conversation_rounds,
            "analysis_timestamp": analysis_timestamp,
            "reasoning": f"基于{conversation_rounds}轮对话调用LLM进行性格分析",
            "llm_prompt": prompt,
            "analysis_method": "llm_based",
        }


    @staticmethod
    def build_llm_personality_prompt(conversation: str, user_id: str) -> str:
        """构建LLM性格分析提示词"""
        return f"""
你是专业的性格分析专家，请基于以下对话内容进行深度性格分析。

对话内容：
{conversation}

用户ID：{user_id}

请从以下维度进行综合分析：

1. MBTI人格特征分析：
   - 内向/外向 (Introversion/Extraversion)：能量来源和社交偏好
   - 感觉/直觉 (Sensing/Intuition)：信息收集方式
   - 思考/情感 (Thinking/Feeling)：决策方式
   - 判断/知觉 (Judging/Perceiving)：生活方式和结构偏好

2. 沟通模式分析：
   - 语言风格：正式/非正式、简洁/详细、直接/委婉
   - 表达方式：理性/感性、内敛/外放、主动/被动
   - 互动模式：提问频率、回应速度、话题转换

3. 行为模式分析：
   - 社交偏好：独立/群体、领导/跟随、竞争/合作
   - 决策风格：快速/谨慎、直觉/分析、冒险/保守
   - 情感表达：内敛/外放、稳定/波动、积极/消极

4. 生活态度分析：
   - 价值观：成就导向/关系导向、传统/创新、个人/集体
   - 应对方式：积极/消极、主动/被动、乐观/悲观
   - 兴趣倾向：技术/艺术、理论/实践、个人/社交

请严格按照以下JSON格式返回分析结果，不要添加任何其他内容：
{{
    "mbti_type": {{
        "introversion_extraversion": 0.0-1.0,
        "sensing_intuition": 0.0-1.0,
        "thinking_feeling": 0.0-1.0,
        "judging_perceiving": 0.0-1.0
    }},
    "communication_style": "详细描述用户的沟通风格",
    "emotional_expression": "详细描述用户的情感表达方式",
    "social_preference": "详细描述用户的社交偏好",
    "life_attitude": "详细描述用户的生活态度",
    "key_observations": ["关键观察点1", "关键观察点2", "关键观察点3"],
    "reasoning": "分析推理过程"
}}
"""

    @staticmethod
    def build_multi_round_personality_prompt(conversation: str, user_id: str) -> str:
        """构建多轮对话性格分析提示词（保留兼容性）"""
        return PersonalityRecognitionTemplates.build_llm_personality_prompt(conversation, user_id)

    @staticmethod
    def analyze_personality_keywords(conversation_lower: str) -> dict:
        """基于关键词进行性格特征分析"""
        # MBTI人格关键词匹配
        mbti_scores = {
            "introversion_extraversion": 0.5,
            "sensing_intuition": 0.5,
            "thinking_feeling": 0.5,
            "judging_perceiving": 0.5,
        }

        # 内向/外向关键词
        introversion_extraversion_keywords = {
            "positive": ["朋友", "聚会", "社交", "活跃", "热情", "兴奋", "团队", "分享", "表达"],
            "negative": ["独处", "安静", "内向", "害羞", "沉默", "个人"],
        }

        # 感觉/直觉关键词
        sensing_intuition_keywords = {
            "positive": ["创新", "想法", "新", "有趣", "探索", "学习", "好奇", "创意", "艺术", "哲学"],
            "negative": ["传统", "保守", "固定", "习惯", "常规", "稳定"],
        }

        # 思考/情感关键词
        thinking_feeling_keywords = {
            "positive": ["帮助", "理解", "关心", "合作", "友善", "宽容", "支持", "同情"],
            "negative": ["批评", "争论", "对抗", "自私", "冷漠", "敌意"],
        }

        # 判断/知觉关键词
        judging_perceiving_keywords = {
            "positive": ["计划", "目标", "完成", "责任", "认真", "仔细", "准时", "组织", "效率"],
            "negative": ["随意", "拖延", "马虎", "混乱", "懒散", "不负责任"],
        }

        # 计算各维度得分
        dimensions = [
            ("introversion_extraversion", introversion_extraversion_keywords),
            ("sensing_intuition", sensing_intuition_keywords),
            ("thinking_feeling", thinking_feeling_keywords),
            ("judging_perceiving", judging_perceiving_keywords),
        ]

        for dimension, keywords in dimensions:
            positive_score = sum(
                1 for word in keywords["positive"] if word in conversation_lower
            )
            negative_score = sum(
                1 for word in keywords["negative"] if word in conversation_lower
            )

            if positive_score > 0 or negative_score > 0:
                total_score = positive_score + negative_score
                adjustment = (positive_score - negative_score) / total_score * 0.3
                mbti_scores[dimension] = max(0.1, min(0.9, 0.5 + adjustment))

        # 分析其他特征
        def analyze_trait(keywords_list, default="平衡型"):
            for keywords in keywords_list:
                if any(word in conversation_lower for word in keywords):
                    return keywords[0]  # 返回第一个关键词对应的类型
            return default

        communication_style = analyze_trait(
            [["详细型", "详细", "解释", "说明", "分析"], ["简洁型", "简单", "直接", "简洁"]]
        )

        emotional_expression = analyze_trait(
            [["感性型", "感觉", "情感", "心情", "开心", "难过"], ["理性型", "逻辑", "分析", "理性", "客观"]]
        )

        social_preference = analyze_trait(
            [["群体型", "朋友", "团队", "合作", "分享"], ["独立型", "独处", "个人", "独立", "自己"]]
        )

        life_attitude = analyze_trait(
            [["乐观型", "乐观", "积极", "希望", "美好"], ["悲观型", "悲观", "消极", "担心", "困难"]]
        )

        return {
            "mbti_type": mbti_scores,
            "communication_style": communication_style,
            "emotional_expression": emotional_expression,
            "social_preference": social_preference,
            "life_attitude": life_attitude,
        }

    @staticmethod
    def process_llm_personality_result(llm_result: str, base_analysis: dict) -> dict:
        """处理LLM返回的性格分析结果"""
        try:
            import json
            # 解析LLM返回的JSON结果
            llm_data = json.loads(llm_result)
            
            # 合并基础分析数据和LLM分析结果
            return {
                **base_analysis,
                "mbti_type": llm_data.get("mbti_type", {}),
                "communication_style": llm_data.get("communication_style", "待分析"),
                "emotional_expression": llm_data.get("emotional_expression", "待分析"),
                "social_preference": llm_data.get("social_preference", "待分析"),
                "life_attitude": llm_data.get("life_attitude", "待分析"),
                "key_observations": llm_data.get("key_observations", []),
                "llm_reasoning": llm_data.get("reasoning", ""),
                "analysis_method": "llm_based",
                "llm_success": True,
            }
        except Exception as e:
            # LLM解析失败时，返回基础分析数据
            return {
                **base_analysis,
                "mbti_type": {
                    "introversion_extraversion": 0.5,
                    "sensing_intuition": 0.5,
                    "thinking_feeling": 0.5,
                    "judging_perceiving": 0.5,
                },
                "communication_style": "待分析",
                "emotional_expression": "待分析",
                "social_preference": "待分析",
                "life_attitude": "待分析",
                "key_observations": [],
                "llm_reasoning": f"LLM解析失败: {str(e)}",
                "analysis_method": "llm_based",
                "llm_success": False,
                "error": str(e),
            }

    @staticmethod
    def accumulate_personality_data(existing_data: dict, new_analysis: dict) -> dict:
        """累积多轮对话的性格分析数据，包含历史记录"""
        if not existing_data:
            return {
                **new_analysis,
                "analysis_history": [new_analysis],
                "total_analyses": 1,
            }

        # 获取现有历史记录
        existing_history = existing_data.get("analysis_history", [])
        total_analyses = existing_data.get("total_analyses", 0) + 1

        # 添加新的分析结果到历史记录
        updated_history = existing_history + [new_analysis]

        # 只保留最近10次分析记录
        if len(updated_history) > 10:
            updated_history = updated_history[-10:]

        # 计算累积的MBTI人格得分（加权平均）
        accumulated_mbti = (
            PersonalityRecognitionTemplates.calculate_weighted_mbti(updated_history)
        )

        # 更新其他特征（使用最新的分析结果）
        return {
            "user_id": new_analysis.get("user_id"),
            "personality": "accumulated",
            "conversation_rounds": new_analysis.get("conversation_rounds", 0),
            "min_required_rounds": PersonalityRecognitionTemplates.MIN_CONVERSATION_ROUNDS,
            "analysis_timestamp": new_analysis.get("analysis_timestamp", ""),
            "reasoning": f"基于{total_analyses}次LLM分析的累积结果",
            "mbti_type": accumulated_mbti,
            "communication_style": new_analysis.get("communication_style", "待分析"),
            "emotional_expression": new_analysis.get("emotional_expression", "待分析"),
            "social_preference": new_analysis.get("social_preference", "待分析"),
            "life_attitude": new_analysis.get("life_attitude", "待分析"),
            "analysis_history": updated_history,
            "total_analyses": total_analyses,
            "last_updated": datetime.now().isoformat(),
            "analysis_method": "llm_based",
        }

    @staticmethod
    def calculate_weighted_mbti(history_records: List[dict]) -> dict:
        """计算加权平均的MBTI人格得分"""
        if not history_records:
            return {
                "introversion_extraversion": 0.5,
                "sensing_intuition": 0.5,
                "thinking_feeling": 0.5,
                "judging_perceiving": 0.5,
            }

        # 计算权重：越近的分析权重越高
        total_weight = 0
        weighted_scores = {
            "introversion_extraversion": 0.0,
            "sensing_intuition": 0.0,
            "thinking_feeling": 0.0,
            "judging_perceiving": 0.0,
        }

        for i, record in enumerate(history_records):
            weight = i + 1  # 权重递增
            total_weight += weight

            mbti_data = record.get("mbti_type", {})
            for trait in weighted_scores:
                score = mbti_data.get(trait, 0.5)
                weighted_scores[trait] += score * weight

        # 计算加权平均
        if total_weight > 0:
            for trait in weighted_scores:
                weighted_scores[trait] = round(weighted_scores[trait] / total_weight, 3)

        return weighted_scores

    @staticmethod
    def get_personality_summary(personality_data: dict) -> str:
        """生成性格分析摘要"""
        if not personality_data:
            return "暂无性格分析数据"

        mbti_data = personality_data.get("mbti_type", {})
        total_analyses = personality_data.get("total_analyses", 0)

        summary = f"基于{total_analyses}次对话分析\n\n"
        summary += "MBTI人格特征：\n"

        trait_descriptions = {
            "introversion_extraversion": "内向/外向",
            "sensing_intuition": "感觉/直觉",
            "thinking_feeling": "思考/情感",
            "judging_perceiving": "判断/知觉",
        }

        for trait, description in trait_descriptions.items():
            score = mbti_data.get(trait, 0.5)
            if score >= 0.7:
                level = "高"
            elif score >= 0.4:
                level = "中"
            else:
                level = "低"
            summary += f"- {description}: {level} ({score:.3f})\n"

        return summary

    @staticmethod
    def get_llm_analysis_workflow(conversation: str, user_id: str, existing_personality_data: dict = None):
        """获取完整的LLM性格分析工作流程"""
        # 1. 生成基础分析数据
        base_analysis = PersonalityRecognitionTemplates.analyze_conversation_only(
            conversation, user_id, existing_personality_data
        )
        
        # 2. 返回LLM提示词和基础数据，供外部调用LLM
        return {
            "prompt": base_analysis.get("llm_prompt"),
            "base_analysis": base_analysis,
            "user_id": user_id,
            "conversation_rounds": base_analysis.get("conversation_rounds", 0),
        }

    @staticmethod
    def complete_llm_analysis_workflow(conversation: str, user_id: str, llm_result: str, existing_personality_data: dict = None):
        """完成完整的LLM性格分析工作流程"""
        # 1. 生成基础分析数据
        base_analysis = PersonalityRecognitionTemplates.analyze_conversation_only(
            conversation, user_id, existing_personality_data
        )
        
        # 2. 处理LLM返回结果
        llm_analysis = PersonalityRecognitionTemplates.process_llm_personality_result(
            llm_result, base_analysis
        )
        
        # 3. 累积到历史数据
        if existing_personality_data:
            final_result = PersonalityRecognitionTemplates.accumulate_personality_data(
                existing_personality_data, llm_analysis
            )
        else:
            final_result = {
                **llm_analysis,
                "analysis_history": [llm_analysis],
                "total_analyses": 1,
            }
        
        return final_result
